Skip to content

fix: role-mention only matches bot's own roles (with guild_create cache)#246

Open
chengli wants to merge 1 commit intoopenabdev:mainfrom
chengli:feat/role-mention-filter
Open

fix: role-mention only matches bot's own roles (with guild_create cache)#246
chengli wants to merge 1 commit intoopenabdev:mainfrom
chengli:feat/role-mention-filter

Conversation

@chengli
Copy link
Copy Markdown

@chengli chengli commented Apr 12, 2026

Summary

  • Fix role-mention detection to only match roles assigned to the receiving bot, preventing cross-triggers in multi-bot guilds
  • Cache the bot's own role IDs from guild_create events (not ready) in a RwLock<HashSet> — zero per-message API calls
  • Early-exit when msg.mention_roles is empty (skip cache read entirely)

Closes #245

Details

Bug: msg.mention_roles.iter().any(|r| msg.content.contains(...)) triggers on any role mentioned in the message, not just the bot's own roles. In a guild with bots A (role X) and B (role Y), mentioning role Y incorrectly wakes up bot A.

Fix: replace string matching with a set intersection against the bot's cached roles:

let is_role_mentioned = if !msg.mention_roles.is_empty() {
    let cached_roles = self.bot_role_ids.read().await;
    msg.mention_roles.iter().any(|r| cached_roles.contains(&r.get()))
} else {
    false
};

Technical notes:

  1. Why guild_create instead of ready? ready.guilds contains UnavailableGuild stubs. Guild member data may not be available yet, particularly for larger guilds, causing .member() lookups to 404. guild_create fires per guild after ready with complete data.

  2. Global HashSet vs per-guild HashMap: We use a flat HashSet<u64> for the cache. Discord Role IDs are globally unique and msg.mention_roles only contains roles valid for the current guild, so a flat cache is safe and keeps lookups simple.

  3. Known limitation: If a role is added to the bot while it is running, it won't be recognized until restart. A guild_member_update handler could keep the cache hot if dynamic role assignment becomes a requested feature.

Files changed

File Change
src/discord.rs Add bot_role_ids: Arc<RwLock<HashSet<u64>>> to Handler; replace string-match with cache lookup; add guild_create handler to populate cache
src/main.rs Initialize empty bot_role_ids cache

Test plan

  • cargo check passes ✅ (verified locally)
  • Single-bot guild: role mention still triggers the bot
  • Multi-bot guild: role-mentioning bot A's role does NOT trigger bot B
  • Bot has no guild roles: role mention does not trigger the bot
  • Large guild: role cache populates correctly via guild_create
  • No role mentions in message: early-exit, no cache read

The existing role-mention check matched any role mentioned in the
message, not just roles assigned to the receiving bot. In multi-bot
guilds this caused cross-triggering: mentioning bot B's role would
also wake up bot A.

Replace string matching against msg.content with a set intersection
against the bot's own cached role IDs. The cache is populated from
guild_create events (not ready, which only has UnavailableGuild stubs
for larger guilds) and stored in a RwLock<HashSet<u64>>. Early-exit
when msg.mention_roles is empty to skip the cache read entirely.

Closes openabdev#245
@masami-agent
Copy link
Copy Markdown
Contributor

Review — PR #246

Good fix for a real multi-bot guild problem. The approach is correct.

✅ What looks good

  1. guild_create over ready — correct choice. ready.guilds only has UnavailableGuild stubs for larger guilds, so role data isn't available there.
  2. Arc<RwLock<HashSet<u64>>> — appropriate shared state pattern. Discord Role IDs are globally unique, so a flat set works.
  3. Fast pathmention_roles.is_empty() check avoids acquiring the read lock when there are no role mentions.
  4. Error handlingguild_create failure logs a warning but doesn't crash the bot.

🔴 Must fix before merge

1. Merge conflict with main
src/main.rs handler struct initialization has changed significantly on main (new fields: router, adapter, allow_bot_messages, trusted_bot_ids; removed: pool, reactions_config). Please rebase onto latest main.

2. CI not triggered
This is a fork PR — CI needs maintainer approval to run. Once rebased, a maintainer will approve the workflow run.

🟡 Non-blocking

3. Role cache not updated after guild_create
If the bot is assigned a new role after startup, the cache won't reflect it until next restart. Consider adding a guild_member_update listener in a follow-up PR.

Summary

Logic is sound, minimal change, solves a real problem. Rebase onto main and we're good to approve.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

closing-soon PR missing Discord Discussion URL — will auto-close in 3 days needs-rebase p2 Medium — planned work pending-contributor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix: role mentions trigger unintended bots in multi-bot guilds

4 participants